﻿namespace NTLib.Pipe.Providers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using NTLib.Pipe.Descriptors;
    using NTLib.Core.Attributes;
    using NTLib.Pipe.Containers;


    /// <summary>
    /// Define a provider to provide MemoryPipe
    /// </summary>
    [GuidAttribute("3b006d25-c029-420d-87c0-9fd2cec88d98")]
    public class MemoryProvider : BasePipeProvider
    {
        #region Fields

        private readonly Guid _providerId = Guid.NewGuid();

        #endregion

        #region Properties

        /// <summary>
        /// Gets the identifier.
        /// </summary>
        public override Guid Id
        {
            get { return this._providerId; }
        }

        #endregion

        /// <summary>
        /// Determines whether this instance can managed target the specified target.
        /// </summary>
        /// <param name="desc">Target description used to define the target.</param>
        /// <param name="token"></param>
        /// <returns>
        ///   <c>true</c> if the provider can managed the specific target.
        /// </returns>
        public override Task<bool> CanManagedTargetAsync(ITargetDescriptor desc, CancellationToken token = default(CancellationToken))
        {
            return Task.FromResult<bool>(desc != null && desc is LocalTargetDescription);
        }

        /// <summary>
        /// Called to create the specific pipe source associate the target.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="type">The type of the pipe.</param>
        /// <param name="target">The target of the pipe.</param>
        /// <param name="token">The cancel token.</param>
        /// <returns>
        /// IPipeSource that could managed object transfert in both ways.
        /// </returns>
        protected override async Task<IPipe<T>> OnCreateSourceAsync<T>(PipeType type, ITargetDescriptor target, CancellationToken token)
        {
            var memoryPipe = base._type.Get<MemoryPipeSource<T>>();
            await memoryPipe.InitializeAsync(target, type, token);

            PipeUsingSource<T> pipe = base._type.Get<PipeUsingSource<T>>();
            pipe.SetSource(memoryPipe, type);
            return pipe;
        }
    }
}
